package com.gxp.web.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gxp.common.annotation.Audit;
import com.gxp.common.config.GxPConfig;
import com.gxp.common.constant.UserConstants;
import com.gxp.common.core.controller.BaseController;
import com.gxp.common.core.domain.AjaxResult;
import com.gxp.common.core.domain.entity.SysUser;
import com.gxp.common.core.page.TableDataInfo;
import com.gxp.common.enums.BusinessAction;
import com.gxp.common.enums.BusinessTitle;
import com.gxp.common.utils.DateUtils;
import com.gxp.common.utils.DictUtils;
import com.gxp.common.utils.ShiroUtils;
import com.gxp.common.utils.StringUtils;
import com.gxp.common.utils.file.FileUploadUtils;
import com.gxp.common.utils.file.FileUtils;
import com.gxp.framework.shiro.audit.AuditService;
import com.gxp.system.domain.*;
import com.gxp.system.domain.dto.ServicesDto;
import com.gxp.system.mapper.ZknjReqSamInfMapper;
import com.gxp.system.mapper.ZknjSampleMapper;
import com.gxp.system.mapper.ZknjServiceInstanceMapper;
import com.gxp.system.service.*;
import org.apache.ibatis.annotations.Param;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 请求Controller
 *
 * @author zh
 * @date 2024-08-06
 */
@Controller
@RequestMapping("/system/request2")
public class ZknjRequestController extends BaseController
{
    private String prefix = "system/request2";

    @Autowired
    private IZknjRequestService zknjRequestService;
    @Autowired
    private IZknjServiceService zknjServiceService;
    @Autowired
    private IZknjMethodService methodService;
    @Autowired
    private IZknjProjectService projectService;
    @Autowired
    private IZknjServiceInstanceService zknjServiceInstanceService;
    @Autowired
    private IZknjServiceApproveService zknjServiceApproveService;
    @Autowired
    private IZkSolventService solventService;
    @Autowired
    private IZknjFavouriteService favouriteService;
    @Autowired
    private IZkInstrumentService instrumentService;
    @Autowired
    private IZkNmrFileService nmrFileService;
    @Autowired
    private IZknjReqSamInfService zknjReqSamInfService;
    @Autowired
    private IZkAuditService zkAuditService;
    @Autowired
    private ZknjSampleMapper sampleMapper;
    @Autowired
    private ZknjServiceInstanceMapper zknjServiceInstanceMapper;
    @Autowired
    private ZknjReqSamInfMapper reqSamInfMapper;
    @Autowired
    private AuditService auditService;
    @Autowired
    private IZknjFileService fileService;
    @Autowired
    private IZknjDocumentService documentService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private IZknjBadgeService zknjBadgeService;


    @RequiresPermissions("system:request:view")
    @GetMapping()
    public String request()
    {
        return prefix + "/request";
    }

    /**
     * 查询请求列表
     */
    @RequiresPermissions("system:request:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(ZknjRequest zknjRequest)
    {
        //分角色获取请求列表
        Long roleId = getSysUser().getRoles().get(0).getRoleId();
        List<ZknjRequest> list = new ArrayList<>();
        if(roleId == UserConstants.ROLE_REQUESTER){
            zknjRequest.setCreateBy(getLoginName());
            startPage();
            list = zknjRequestService.selectZknjRequestList(zknjRequest);
        }else if (roleId == UserConstants.ROLE_VERIFIER){
            //根据userId查询projectId，获取project下的所有request，添加验证信息
            List<ZknjProject> projects = projectService.selectZknjProjectByUser(getUserId());
            List<Long> proIds = projects.stream()
                    .filter(p -> p.getProStatus() == 0L)
                    .filter(p -> p.getStartTime() == null ? p.getProId()>0 : p.getStartTime().getTime() < DateUtils.getNowDate().getTime())
                    .filter(p -> p.getEndTime() == null ? p.getProId()>0 : p.getEndTime().getTime() > DateUtils.getNowDate().getTime())
                    .map(ZknjProject::getProId)
                    .collect(Collectors.toList());
            startPage();
            zknjRequest.setProIds(proIds.toArray(new Long[0]));
//            zknjRequest.setReqStatus(Long.valueOf(DictUtils.getDictValue("sys_request_status","pending verification")));
            list = zknjRequestService.selectZknjRequestListForVerify(zknjRequest);
        }else if(roleId == UserConstants.ROLE_APPROVER){
            //QA审核界面
            //QA可以查看所有request
            startPage();
            zknjRequest.setReqStatus(Long.valueOf(DictUtils.getDictValue("sys_request_status","pending QA approval")));
            list = zknjRequestService.selectZknjRequestList(zknjRequest);
        }

        return getDataTable(list);
    }

    /**
     * 新增请求
     */
    @GetMapping("/add")
    public String add(ModelMap mmap)
    {
        List<ZknjProject> projects = projectService.selectZknjProjectByUser(getUserId());
        List<ZknjProject> collect = projects.stream()
                .filter(p -> p.getProStatus() == 0L)
                .filter(p -> p.getStartTime() == null ? p.getProId()>0 : p.getStartTime().getTime() < DateUtils.getNowDate().getTime())
                .filter(p -> p.getEndTime() == null ? p.getProId()>0 : p.getEndTime().getTime() > DateUtils.getNowDate().getTime())
                .collect(Collectors.toList());
        mmap.addAttribute("projects", collect);
        return prefix + "/add3";
    }

    @RequiresPermissions("system:request:add")
    @Audit(businessTitle = BusinessTitle.REQUEST, businessAction = BusinessAction.CREATED, description = "添加请求")
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(ZknjRequest zknjRequest)
    {
        zknjRequest.setCreateBy(getLoginName());
        ZknjProject project = projectService.selectZknjProjectByProId(zknjRequest.getProId());
        int row = zknjRequestService.insertZknjRequest(zknjRequest);
        return toAjax(row, zknjRequest.getReqId())
                .put("Request Name", zknjRequest.getReqName())
                .put("Parent", project.getProName())
                .put("Parent Type", BusinessTitle.PROJECT.getInfo())
                .put("Description", zknjRequest.getReqDes());
    }

    /**
     * 修改请求
     */
    @RequiresPermissions("system:request:edit")
    @GetMapping("/edit/{reqId}")
    public String edit(@PathVariable("reqId") Long reqId, ModelMap mmap)
    {
        ZknjRequest zknjRequest = zknjRequestService.selectZknjRequestByReqId(reqId);
        List<ZkSolvent> solvents = solventService.selectAll();
        List<ZkInstrument> instruments = instrumentService.selectZkInstrumentListByReqId(reqId);
        List<ZknjService> services = zknjServiceService.selectZknjServicesByReqId(reqId, true);

        List<ZknjService> collect = services.stream().filter(service -> service.getSerStatus() == 0).collect(Collectors.toList());
        mmap.put("zknjRequest", zknjRequest);
        mmap.put("services", collect);
        mmap.put("instruments", instruments.stream().filter(instrument -> instrument.getStatus() == 0).collect(Collectors.toList()));
        mmap.put("solvents", solvents);
        return prefix + "/edit";
    }

    /**
     * 修改保存请求
     */
    @RequiresPermissions("system:request:edit")
    @Audit(businessTitle = BusinessTitle.REQUEST, businessAction = BusinessAction.UPDATED, description = "修改请求")
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(ZknjRequest zknjRequest)
    {
        zknjRequest.setUpdateBy(getLoginName());
        ZknjProject project = projectService.selectZknjProjectByProId(zknjRequest.getProId());
        List<ZknjSample> samplesNew = zknjRequest.getSamples();
        if (samplesNew == null || samplesNew.isEmpty()) {
            return toAjax(zknjRequestService.updateZknjRequest(zknjRequest), zknjRequest.getReqId())
                    .put("Request Name", zknjRequest.getReqName())
                    .put("Parent", project.getProName())
                    .put("Parent Type", BusinessTitle.PROJECT.getInfo())
                    .put("Description", zknjRequest.getReqDes());
        }
        List<ZknjSample> samplesOld = sampleMapper.selectZknjSampleByReqId(zknjRequest.getReqId());
        List<Long> samIdsOld = samplesOld.stream().map(ZknjSample::getSamId).collect(Collectors.toList());
        List<Long> samIdsNew = samplesNew.stream().map(ZknjSample::getSamId).collect(Collectors.toCollection(ArrayList::new));  // 防止出现空指针
        List<Long> delSamIds = samIdsOld.stream().filter(samId -> !samIdsNew.contains(samId)).collect(Collectors.toList());
        delSamIds.forEach(samId ->{
            List<ZknjServiceInstance> zknjServiceInstances = zknjServiceInstanceMapper.selectListBySamId(samId);
            //Delete Sample
            sampleMapper.deleteZknjSampleBySamId(samId);
            //Delete Service
            zknjServiceInstanceMapper.deleteListBySamId(samId);
            //Delete Relation
            reqSamInfMapper.deleteZknjReqSamBySamId(samId);
            //Audit
            zknjServiceInstances.forEach(zknjServiceInstance -> {
                ZknjMethod method = methodService.selectZknjMethodByModId(zknjServiceInstance.getModId());
                Map<String, String> map = new HashMap<>();
                map.put("Services Name", zknjServiceInstance.getSerName());
                map.put("entityId", String.valueOf(zknjServiceInstance.getInfId()));
                map.put("Sample Name", zknjServiceInstance.getSample().getSamName());
                map.put("Service Type", zknjServiceInstance.getSvtypeName());
                map.put("Method Name", method == null ? "-" : method.getModName());
                String params = null;
                //map转json字符串
                try {
                    params = new ObjectMapper().writeValueAsString(map);
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                }

                auditService.recordAuditSuccess(BusinessTitle.SERVICE.getInfo(), BusinessAction.DELETED.ordinal(),
                        "删除服务", params);
            });

        });
        samplesNew.forEach(sample -> {
            if(sample.getSamId() == null){
                //Add sample
                sample.setCreateBy(ShiroUtils.getLoginName());
                sample.setCreateTime(DateUtils.getNowDate());
                sampleMapper.insertZknjSample(sample);
                //
                List<Map<String, String>> servicesAudit = new ArrayList<>();
                zknjRequestService.insertReqSamMod(sample, zknjRequest.getReqId(), servicesAudit);
                // Audit
                servicesAudit.forEach(s -> {
                    String params = null;
                    //map转json字符串
                    try {
                        params = new ObjectMapper().writeValueAsString(s);
                    } catch (JsonProcessingException e) {
                        throw new RuntimeException(e);
                    }
                    auditService.recordAuditSuccess(BusinessTitle.SERVICE.getInfo(), BusinessAction.CREATED.ordinal(),
                            "添加服务", params);
                });

            }else {
                //Edit Sample
                sample.setUpdateBy(ShiroUtils.getLoginName());
                sample.setUpdateTime(DateUtils.getNowDate());
                sampleMapper.updateZknjSample(sample);
                zknjRequestService.updateReqSamMod(sample, zknjRequest.getReqId());
                //Audit TODO

            }
        });

        return toAjax(zknjRequestService.updateZknjRequest(zknjRequest), zknjRequest.getReqId())
                .put("Request Name", zknjRequest.getReqName())
                .put("Parent", project.getProName())
                .put("Parent Type", BusinessTitle.PROJECT.getInfo())
                .put("Description", zknjRequest.getReqDes());
    }

    /**
     * 删除请求
     */
    @RequiresPermissions("system:request:remove")
    @Audit(businessTitle = BusinessTitle.REQUEST, businessAction = BusinessAction.DELETED, description = "删除请求")
    @PostMapping( "/remove")
    @ResponseBody
    public AjaxResult remove(String ids)
    {
        return toAjax(zknjRequestService.deleteZknjRequestByReqIds(ids));
    }

    /**
     * 取消申请
     */
    @RequiresPermissions("system:request:edit")
    @Audit(businessTitle = BusinessTitle.REQUEST, businessAction = BusinessAction.UPDATED, description = "取消请求")
    @PostMapping("/cancel")
    @ResponseBody
    public AjaxResult cancel(String id){
        return toAjax(zknjRequestService.cancelZknjRequestByReqIds(id), Long.valueOf(id));
    }

    /**
     * 重新提交验证
     */
    @RequiresPermissions("system:request:edit")
    @Audit(businessTitle = BusinessTitle.REQUEST, businessAction = BusinessAction.UPDATED, description = "重新提交验证")
    @PostMapping("/approve")
    @ResponseBody
    public AjaxResult approve(String id){
        return toAjax(zknjRequestService.reapproveZknjRequestByReqIds(id)).put("entityId", Long.valueOf(id));
    }

    /**
     * 验证结果
     */
    @RequiresPermissions("system:request:approve")
    @GetMapping("/verify")
    public String verify(@Validated ZknjServiceInstance zknjServiceInstance, ModelMap mmap)
    {
        Long infId = zknjServiceInstance.getInfId();
        ZknjServiceInstance serviceInstance = zknjServiceInstanceService.selectByInfId(infId);

        String reportfileIds = serviceInstance.getReportfileIds();
        if(reportfileIds != null && !reportfileIds.isEmpty()){
            String[] reportFileIdArray = reportfileIds.split(",");
            for (String reportFileId : reportFileIdArray) {
                //如果reportFiles为空则初始化
                if (zknjServiceInstance.getReportFiles() == null) {
                    zknjServiceInstance.setReportFiles(new ArrayList<>());
                }
                zknjServiceInstance.getReportFiles().add(nmrFileService.selectZkNmrFileByFileId(Long.valueOf(reportFileId)));
            }
        }
        mmap.addAttribute("expcode", serviceInstance.getExpcode());
        mmap.addAttribute("approveBy", getLoginName());
        mmap.addAttribute("reportFiles", zknjServiceInstance.getReportFiles());
        return prefix + "/verify";
    }

    /**
     * 验证结果提交
     */
    @RequiresPermissions("system:request:approve")
    @Audit(businessTitle = BusinessTitle.REQUEST, businessAction = BusinessAction.APPROVED, description = "验证结果提交")
    @PostMapping("/verify")
    @ResponseBody
    public AjaxResult verifySave(@Validated ZknjServiceApprove zknjServiceApprove)
    {
        zknjServiceApprove.setUpdateBy(getLoginName());
        zknjServiceApprove.setApproveTime(DateUtils.getNowDate());
        zknjServiceInstanceService.updateStatusByExpcode(zknjServiceApprove.getExpcode(), zknjServiceApprove.getApproveStatus());

        ZknjServiceInstance serviceInstance = zknjServiceInstanceService.selectZkServiceInstanceByExpcode(zknjServiceApprove.getExpcode());
        //将意见以批注的形式添加到pdf文件中
        if (zknjServiceApprove.getApproveComment() != null && !zknjServiceApprove.getApproveComment().isEmpty()) {
            nmrFileService.addCommentToPdf(serviceInstance.getReportfileIds(), zknjServiceApprove.getApproveComment());
        }

        //修改request状态
        ZknjRequest zknjRequest = zknjRequestService.selectZknjRequestByInfId(serviceInstance.getInfId());
        if(zknjRequest == null){
            return error("验证结果提交失败，请求信息丢失").put("entityId", zknjRequest.getReqId());
        }
        if(zknjRequest.getReqStatus().equals(Long.valueOf(DictUtils.getDictValue("sys_request_status", "Cancelled")))){
            return error("验证结果提交失败，请求已被取消").put("entityId", zknjRequest.getReqId());
        }

        Long approvedStatus = Long.valueOf(DictUtils.getDictValue("sys_service_status", "verified"));
        Long disApprovedStatus = Long.valueOf(DictUtils.getDictValue("sys_service_status", "not verified"));
        //检查所有服务的状态，全部验证通过,修改request状态为通过,有一个验证未通过，则修改request状态为未通过
        List<ZknjServiceInstance> serviceInstances = zknjServiceInstanceService.selectListByReqId(zknjRequest.getReqId());
        boolean allApproved = serviceInstances.stream().allMatch(
                service -> Objects.equals(service.getSerStatus(), approvedStatus));
        //检查是否有not approve的服务
        boolean hasNotApproved = serviceInstances.stream().anyMatch(
                service -> Objects.equals(service.getSerStatus(), disApprovedStatus));
        if(allApproved){
            zknjRequest.setReqStatus(Long.valueOf(DictUtils.getDictValue("sys_request_status","pending QA approval"))); //通过
            zknjRequest.setUpdateTime(DateUtils.getNowDate());
            zknjRequestService.updateZknjRequestStatus(zknjRequest);
            //增加消息通知
            //查询所有审批人   QA 角色人员
            ZknjBadge zknjBadge = new ZknjBadge();
            List<SysUser> approvers = userService.selectUserByRole(UserConstants.ROLE_APPROVER);
            String sampleNames = (zknjRequest.getSamples() != null)
                    ? zknjRequest.getSamples().stream()
                    .map(ZknjSample::getSamName)
                    .reduce((s1, s2) -> s1 + ", " + s2)
                    .orElse("No samples")
                    : "No samples";
            zknjBadge.setEntity("Samples: " + sampleNames);
            zknjBadge.setStatus("N");
            zknjBadge.setDescription("This service has been verified on request '"
                    + zknjRequest.getReqName() + "'. Please, click here to check it.");
            zknjBadge.setUrl("/system/request/");
            zknjBadge.setCreateBy(ShiroUtils.getLoginName());
            zknjBadge.setReceiver(approvers.stream().map(SysUser::getUserName).collect(Collectors.joining(",")));
            zknjBadge.setCreateTime(DateUtils.getNowDate());
            zknjBadge.setTitle("The request '" + zknjRequest.getReqName() + "' is completed");
            zknjBadgeService.insertZknjBadge(zknjBadge);

        }else if(hasNotApproved){
            zknjRequest.setReqStatus(Long.valueOf(DictUtils.getDictValue("sys_request_status","Reject"))); //未通过
            zknjRequest.setUpdateTime(DateUtils.getNowDate());
            zknjRequestService.updateZknjRequestStatus(zknjRequest);
        }
//        AsyncManager.me().execute(AsyncFactory.recordAuditSuccess(BusinessTitle.REQUEST.getInfo(),BusinessAction.APPROVED.ordinal(),"",""));
        return toAjax(zknjServiceApproveService.insertZknjServiceApprove(zknjServiceApprove))
                .put("entityId", zknjRequest.getReqId())
                .put("Status", zknjServiceApprove.getApproveStatus() == approvedStatus ? "Approved" : "Not Approved")
                .put("Comment", zknjServiceApprove.getApproveComment())
                .put("Expcode", zknjServiceApprove.getExpcode());
    }

    /**
     * 验证结果
     */
    @GetMapping("/esignline")
    public String esign(@Validated ZknjServiceInstance zknjServiceInstance, ModelMap mmap)
    {
        Long infId = zknjServiceInstance.getInfId();
        ZknjServiceInstance serviceInstance = zknjServiceInstanceService.selectByInfId(infId);
        List<ZknjServiceApprove> zknjServiceApproves = zknjServiceApproveService.selectZknjServiceApproveByExpcode(serviceInstance.getExpcode());
        //按时间倒叙排序
        zknjServiceApproves.sort((a, b) -> b.getApproveTime().compareTo(a.getApproveTime()));
        mmap.addAttribute("esigns", zknjServiceApproves);
        return prefix + "/esignline";
    }

    @PostMapping("/prolist")
    @ResponseBody
    public TableDataInfo list()
    {
        startPage();
        //TODO admin测试用
        List<ZknjProject> list = projectService.selectZknjProjectList(new ZknjProject());
        return getDataTable(list);
    }

    @GetMapping("/services/{reqId}")
    public String services(@PathVariable("reqId") Long reqId, ModelMap mmap){
        mmap.put("reqId", reqId);
        return prefix + "/services";
    }

    /**
     * 服务列表
     * @param zknjRequest
     * @return
     */
    @PostMapping("/serlist")
    @ResponseBody
    public TableDataInfo serList(ZknjRequest zknjRequest)
    {
        startPage();
        List<ZknjServiceInstance> list = zknjServiceInstanceService.selectListByReqId(zknjRequest.getReqId());
        return getDataTable(list);
    }

    /**
     * request 提交
     */
    @PostMapping("/save")
    @Audit(businessTitle = BusinessTitle.REQUEST, businessAction = BusinessAction.SUBMITTED, description = "提交请求")
    @ResponseBody
    public AjaxResult save(@Validated ZknjRequest zknjRequest)
    {
        Long reqId = zknjRequest.getReqId();
        if(reqId == null){
            return error("提交申请失败，申请已不存在");
        }
        ZknjRequest zkRequest = zknjRequestService.selectZknjRequestByReqId(zknjRequest.getReqId());
        //检查项目信息
        if (zkRequest.getProject() == null) {
            return error("项目信息丢失");
        }
        //检查样品信息
        if (zkRequest.getSamples() == null || zkRequest.getSamples().isEmpty()) {
            return error("样品信息丢失");
        }
        //检查服务信息
        if (zkRequest.getServices() == null || zkRequest.getServices().isEmpty()) {
            return error("服务信息丢失");
        }

        return toAjax(zknjRequestService.submit(zkRequest), zknjRequest.getReqId())
                .put("request Name", zknjRequest.getReqName());
    }

    /**
     * 实验停止
     */
    @PostMapping("/serStop")
    @Audit(businessTitle = BusinessTitle.REQUEST, businessAction = BusinessAction.UPDATED, description = "提交实验停止请求")
    @ResponseBody
    public AjaxResult serStop(@Validated ZknjServiceInstance zknjServiceInstance)
    {
        Long infId = zknjServiceInstance.getInfId();
        ZknjReqSamInf zknjReqSamInf = new ZknjReqSamInf();
        zknjReqSamInf.setInfId(infId);
        List<ZknjReqSamInf> zknjReqSamInfs = zknjReqSamInfService.selectZknjReqSamList(zknjReqSamInf);
        if(zknjReqSamInfs == null || zknjReqSamInfs.isEmpty()){
            return error("提交实验停止请求失败，样品信息丢失");
        }
        if(infId == null || infId < 1){
            return error("提交实验停止请求失败，服务信息丢失");
        }

        return toAjax(zknjServiceInstanceService.stopExpReq(infId), zknjReqSamInfs.get(0).getReqId());
    }

    /**
     * 取消实验验证
     */
    @PostMapping("/cancelVerify")
    @Audit(businessTitle = BusinessTitle.REQUEST, businessAction = BusinessAction.UPDATED, description = "取消实验验证")
    @ResponseBody
    public AjaxResult cancelVerify(@Validated ZknjServiceInstance zknjServiceInstance)
    {
        Long infId = zknjServiceInstance.getInfId();
        if(infId == null || infId < 1){
            return error("取消实验验证失败，服务信息丢失");
        }
        //修改当前service状态为cancel
        ZknjServiceInstance serviceInstance = zknjServiceInstanceService.selectByInfId(infId);
        serviceInstance.setSerStatus(Long.valueOf(DictUtils.getDictValue("sys_service_status", "Cancelled")));
        zknjServiceInstanceService.updateZknjServiceInstance(serviceInstance);

        //修改request状态为cancel
        ZknjRequest zknjRequest = zknjRequestService.selectZknjRequestByInfId(infId);
        if(zknjRequest == null){
            return error("取消实验验证失败，请求信息丢失");
        }
        zknjRequest.setReqStatus(Long.valueOf(DictUtils.getDictValue("sys_request_status", "Cancelled")));
        zknjRequestService.updateZknjRequestStatus(zknjRequest);

        return success();
    }


    /**
     * 修改请求
     */
    @RequiresPermissions("system:request:edit")
    @GetMapping("/serEdit/{infId}")
    public String serEdit(@PathVariable("infId") Long infId, ModelMap mmap)
    {
        ZknjServiceInstance service = zknjServiceInstanceService.selectByInfId(infId);
        ZknjMethod method = methodService.selectZknjMethodByModId(service.getModId());
        mmap.addAttribute("service", service);
        mmap.addAttribute("sample", service.getSample());
        mmap.addAttribute("method", method);
        return prefix + "/serEdit";
    }

    /**
     * 修改保存请求
     */
    @RequiresPermissions("system:request:edit")
    @PostMapping("/serEdit")
    @ResponseBody
    public AjaxResult serEditSave(ZknjSample sample, ZknjServiceInstance serviceActive, @Param("status")String status)
    {
        serviceActive.setPriority(status);
        serviceActive.setUpdateBy(getLoginName());
        serviceActive.setUpdateTime(DateUtils.getNowDate());
        sample.setUpdateBy(getLoginName());
        sample.setUpdateTime(DateUtils.getNowDate());
        return toAjax(zknjRequestService.updateSevAndSam(sample, serviceActive));
    }

    /**
     * 选择服务
     */
    @GetMapping("/selService")
    public String getSelService(ModelMap mmap){

        return prefix + "/table/selectServices";
    }

    /**
     * 选择服务
     */
    @PostMapping("/selServiceList")
    @ResponseBody
    public TableDataInfo serList(ZknjService zknjService)
    {
        zknjService.setSerStatus(11L);
        startPage();
        List<ZknjService> list = zknjServiceService.selectZknjServices(zknjService);
        return getDataTable(list);
    }

    /**
     * 选择方法
     */
    @GetMapping("/selMethod")
    public String getSelMethod(ModelMap mmap, ZknjService service){
        mmap.addAttribute("serId", service.getSerId());
        return prefix + "/table/selectMethod";
    }

    /**
     * 选择方法
     */
    @PostMapping("/selMethodList")
    @ResponseBody
    public TableDataInfo modList(ZknjMethod zknjMethod)
    {
        zknjMethod.setModStatus(2L);
        //激活状态 TODO
        startPage();
        List<ZknjMethod> list = methodService.selectZknjMethodList(zknjMethod);
        return getDataTable(list);
    }

    /**
     * 获取溶剂
     */
    @PostMapping("/selSolvents")
    @ResponseBody
    public List<ZkSolvent> getSolvents(@Param("modId") Long modId) {
        List<ZkSolvent> solvents = methodService.selectZknjMethodByModId(modId).getSolvents();
        return solvents;
    }

    @RequiresPermissions("system:request:edit")
    @GetMapping("/addSam/{reqId}")
    public String addSample(@PathVariable("reqId") Long reqId, ModelMap mmap)
    {
        ZknjRequest zknjRequest = zknjRequestService.selectZknjRequestByReqId(reqId);
        List<ZkSolvent> solvents = solventService.selectAll();
        List<ZkInstrument> instruments = instrumentService.selectZkInstrumentListByReqId(reqId);
        List<ZknjService> services = zknjServiceService.selectZknjServicesByReqId(reqId, true);
        List<ZknjService> collect = services.stream().filter(service -> service.getSerStatus() == 0).collect(Collectors.toList());
        mmap.put("zknjRequest", zknjRequest);
        mmap.put("solvents", solvents);
        mmap.put("instruments", instruments.stream().filter(instrument -> instrument.getStatus() == 0).collect(Collectors.toList()));
        mmap.put("services", collect);
        return prefix + "/addSample";
    }

    /**
     * 根据服务ID获取方法
     */
    @PostMapping("/getMethods")
    @ResponseBody
    public AjaxResult getMethods(ZknjMethod zknjMethod)
    {
        if (zknjMethod == null || zknjMethod.getSerId() == null){
            return AjaxResult.success();
        }
        List<ZknjMethod> methods = methodService.selectZknjMethodList(zknjMethod);
        return AjaxResult.success(methods);
    }

    /**
     * 根据方法ID获取服务和方法信息
     */
    @PostMapping("/getServices")
    @ResponseBody
    public AjaxResult getServices(@Param("modIds") String modIds)
    {
        if (modIds == null || modIds.isEmpty()){
            return AjaxResult.success();
        }

        ServicesDto result = zknjServiceService.selectZknjServiceAndMethodByModIds(modIds);
        return AjaxResult.success(result);
    }

    @RequiresPermissions("system:request:view")
    @GetMapping("/history")
    public String requestHistory()
    {
        return prefix + "/requestHistory";
    }

    @RequiresPermissions("system:request:list")
    @PostMapping("/history/list")
    @ResponseBody
    public TableDataInfo listHistory(ZknjRequest zknjRequest)
    {
        zknjRequest.setCreateBy(getLoginName());
        startPage();
        List<ZknjRequest> list = zknjRequestService.selectZknjRequestListForHistory(zknjRequest);
        return getDataTable(list);
    }

    /**
     * 服务界面下载nmr文件
     */
    @GetMapping("/download")
    public void fileDownload(@RequestParam("id") Long fileId, HttpServletResponse response, HttpServletRequest request){
        try {
            ZkNmrFile nmrFile = nmrFileService.selectZkNmrFileByFileId(fileId);
            String realFileName = nmrFile.getFileName();
            String realFilePath = nmrFile.getFilePathGxp() ;
            String profilePath = GxPConfig.getProfile();
            realFilePath = profilePath + "/" + realFilePath;
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(realFilePath, response.getOutputStream());
        } catch (Exception e) {
            logger.error("下载文件失败", e);
        }
    }

    /**
     * 服务预览PDF文件
     */
    @GetMapping("/preview")
    public void filePreview(@RequestParam("id") Long fileId, HttpServletResponse response, HttpServletRequest request){
        try {
            ZkNmrFile nmrFile = nmrFileService.selectZkNmrFileByFileId(fileId);
            String realFileName = nmrFile.getFileName();
            String realFilePath = nmrFile.getFilePathGxp() ;
            String profilePath = GxPConfig.getProfile();
            realFilePath = profilePath + "/" + realFilePath;
            File file = new File(realFilePath);
            response.setContentType("application/pdf");
//            FileUtils.setAttachmentResponseHeader(response, realFileName);
            response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
            response.setContentLength((int) file.length());
            FileUtils.writeBytes(realFilePath, response.getOutputStream());
        } catch (Exception e) {
            logger.error("预览文件失败", e);
        }
    }

    @GetMapping("/audit/{reqId}")
    public String audit(@PathVariable("reqId") Long reqId, ModelMap mmap){
        mmap.put("reqId", reqId);

        return prefix + "/audit";
    }

    @RequiresPermissions("system:audit:list")
    @PostMapping("/auditList")
    @ResponseBody
    public TableDataInfo list(ZkAudit audit)
    {
        audit.setTitle(BusinessTitle.REQUEST.getInfo());
        startPage();
        List<ZkAudit> list = zkAuditService.selectZkAuditList(audit);
        return getDataTable(list);
    }

    @RequiresPermissions("system:audit:list")
    @PostMapping("/auditList2")
    @ResponseBody
    public TableDataInfo list2(ZkAudit audit)
    {
        audit.setTitle(BusinessTitle.SERVICE.getInfo());
        startPage();
        List<ZkAudit> list = zkAuditService.selectZkAuditListForService(audit);
        return getDataTable(list);
    }

    @RequiresPermissions("system:audit:list")
    @PostMapping("/auditList3")
    @ResponseBody
    public TableDataInfo list3(ZkAudit audit)
    {
        audit.setTitle(BusinessTitle.METHOD.getInfo());
        startPage();
        List<ZkAudit> list = zkAuditService.selectZkAuditListForMethod(audit);
        return getDataTable(list);
    }

    @RequiresPermissions("system:audit:list")
    @PostMapping("/auditList4")
    @ResponseBody
    public TableDataInfo list4(ZkAudit audit)
    {
        audit.setTitle(BusinessTitle.INSTRUMENT.getInfo());
        startPage();
        List<ZkAudit> list = zkAuditService.selectZkAuditListForInstrument(audit);
        return getDataTable(list);
    }

    @RequiresPermissions("system:audit:detail")
    @GetMapping("/detail/{auditId}")
    public String detail(@PathVariable("auditId") Long auditId, ModelMap mmap)
    {
        mmap.put("audit", zkAuditService.selectZkAuditByAuditId(auditId));
        return prefix + "/detail";
    }

    /**
     * 打开上传知识文档界面
     */
    @RequiresPermissions("system:request:edit")
    @GetMapping("/uploadDoc")
    public String uploadDoc(@RequestParam("reqId") Long reqId, ModelMap mmap) {
        mmap.put("reqId", reqId);
        return prefix + "/uploadDoc";
    }

    /**
     * 上传知识文档
     */
    @RequiresPermissions("system:request:edit")
    @PostMapping("/uploadDoc/upload")
    @ResponseBody
    public AjaxResult upload(MultipartFile docFile) throws Exception {
        if (docFile == null || docFile.isEmpty()) {
            return error("上传文件不能为空");
        }
        // 保存文件到zknj_file数据库
        // 获取文件名和路径
        String filePath = GxPConfig.getUploadPath() + "/documents/";
        String fileUrl = FileUploadUtils.upload2(filePath, docFile);

        // 保存数据库
        ZknjFile zknjFile = new ZknjFile();
        zknjFile.setFileName(docFile.getOriginalFilename());
        zknjFile.setFilePathGxp(fileUrl);
        zknjFile.setFileType("Document");
        zknjFile.setUploadBy(ShiroUtils.getLoginName());
        zknjFile.setUploadTime(DateUtils.getNowDate());
        zknjFile.setFileSize(docFile.getSize());
        zknjFile.setValidTime(DateUtils.addDays(DateUtils.getNowDate(), 1)); // 设置有效期为1天
        fileService.insertZknjFile(zknjFile);
        return success().put("fileId", zknjFile.getFileId())
                .put("fileName", zknjFile.getFileName())
                .put("data", "文件上传成功");
    }

    /**
     * 上传知识文档
     */
    @RequiresPermissions("system:request:edit")
    @PostMapping("/uploadDoc")
    @ResponseBody
    public AjaxResult uploadDoc(ZknjDocument document) {
        int row = documentService.insertZknjDocument(document);
        if (row > 0) {
            //修改附件的有效期
            String[] fileIds = document.getDocFileIds().split(",");
            for (String fileId : fileIds) {
                ZknjFile zknjFile = fileService.selectZknjFileByFileId(Long.parseLong(fileId));
                if (zknjFile != null) {
                    zknjFile.setValidTime(DateUtils.addDays(DateUtils.getNowDate(), 365 * 5)); // 设置有效期为5年
                    fileService.updateZknjFile(zknjFile);
                }
            }
        }
        return toAjax(row);
    }

    /**
     * 显示文档
     * @param reqId
     * @return
     */
    @GetMapping("/showDocument")
    public String showDocument(@RequestParam("reqId") Long reqId, ModelMap mmap) {
        ZknjRequest zknjRequest = zknjRequestService.selectZknjRequestByReqId(reqId);
        for (ZknjDocument doc : zknjRequest.getDocuments()) {
            if(doc.getDocId() == null){
                continue;
            }
            List<ZknjFile> fileList = new ArrayList<>();
            if (StringUtils.isNotEmpty(doc.getDocFileIds())) {
                String[] ids = doc.getDocFileIds().split(",");
                for (String id : ids) {
                    ZknjFile file = fileService.selectZknjFileByFileId(Long.parseLong(id));
                    if (file != null) {
                        fileList.add(file);
                    }
                }
            }
            doc.setFiles(fileList);
        }
        mmap.put("documents", zknjRequest.getDocuments());

        return prefix + "/document";
    }

    @PostMapping("updateDocument")
    @ResponseBody
    public AjaxResult updateDocument(ZknjDocument document) {
        if (document.getDocId() == null) {
            return error("文档ID不能为空");
        }
        int row = documentService.updateZknjDocument(document);
        if (row > 0) {
            //修改附件的有效期
            String[] fileIds = document.getDocFileIds().split(",");
            for (String fileId : fileIds) {
                ZknjFile zknjFile = fileService.selectZknjFileByFileId(Long.parseLong(fileId));
                if (zknjFile != null) {
                    zknjFile.setValidTime(DateUtils.addDays(DateUtils.getNowDate(), 365 * 5)); // 设置有效期为5年
                    fileService.updateZknjFile(zknjFile);
                }
            }
        }
        return toAjax(row);
    }

    /**
     * 界面下载document
     */
    @GetMapping("/downloadFile/{fileId}")
    public void downloadFile(@PathVariable("fileId") Long fileId, HttpServletResponse response, HttpServletRequest request){
        try {
            ZknjFile file = fileService.selectZknjFileByFileId(fileId);
            String realFileName = file.getFileName();
            String realFilePath = file.getFilePathGxp() ;
            String profilePath = GxPConfig.getProfile();
            realFilePath = profilePath + "/" + realFilePath;
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(realFilePath, response.getOutputStream());
        } catch (Exception e) {
            logger.error("下载文件失败", e);
        }
    }

    /**
     * QA审核界面
     */
//    @RequiresPermissions("system:request:approve")
    @GetMapping("/approveQA")
    public String approveQA(@Validated ZknjRequest zknjRequest, ModelMap mmap)
    {
        mmap.put("reqId", zknjRequest.getReqId());
        mmap.put("approveBy", getLoginName());
        return prefix + "/approveQA";
    }

    /**
     * 修改保存QA审核结果
     */
    @PostMapping("/approveQA")
    @ResponseBody
    public AjaxResult approveQA(ZknjRequest zknjRequest)
    {
//        zkInstrument.setUpdateBy(getLoginName());
        return toAjax(zknjRequestService.updateZknjRequest(zknjRequest));
    }

    /**
     * 打开审核意见界面
     * @param auditId
     * @param mmap
     * @return
     */
//    @RequiresPermissions("system:request:approve")
    @GetMapping("/openCommentView")
    public String openCommentView(@RequestParam("auditId") Long auditId, ModelMap mmap)
    {
        mmap.put("auditId", auditId);
        return prefix + "/approveComment";
    }

    /**
     * 审核意见提交
     * @param zkAudit
     * @return
     */
    @PostMapping("/approveComment")
    @ResponseBody
    public AjaxResult approveComment(@Validated ZkAudit zkAudit)
    {
        //TODO 再次comment的逻辑（在comment之后加上）
        return toAjax(zkAuditService.updateZkAudit(zkAudit));
    }

    /**
     * 样品详情界面
     */
    @GetMapping("/samview/{samId}")
    public String sampleDetail(@PathVariable("samId") Long samId, ModelMap mmap) {
        ZknjSample zknjSample = sampleMapper.selectZknjSampleBySamId(samId);
        if (zknjSample == null) {
            return prefix + "/error";
        }
        mmap.put("sample", zknjSample);
        mmap.put("services",  zknjServiceInstanceMapper.selectListBySamId(samId));
        return prefix + "/viewSample";
    }

    /**
     * 服务详情界面
     */
    @GetMapping("/serview/{infId}")
    public String serviceDetail(@PathVariable("infId") Long infId, ModelMap mmap) {
        ZknjServiceInstance serviceInstance = zknjServiceInstanceService.selectByInfId(infId);
        if (serviceInstance == null) {
            return prefix + "/error";
        }
        ZknjMethod method = methodService.selectZknjMethodByModId(serviceInstance.getModId());
        List<ZknjServiceApprove> zknjServiceApproves = zknjServiceApproveService.selectZknjServiceApproveByExpcode(serviceInstance.getExpcode());
        //按时间倒叙排序
        if( zknjServiceApproves == null || zknjServiceApproves.isEmpty()){
            mmap.put("verifier", "No verifier");
        }else {
            zknjServiceApproves.sort((a, b) -> b.getApproveTime().compareTo(a.getApproveTime()));
            mmap.put("verifier", zknjServiceApproves.get(0).getApproveBy());
        }
        if(serviceInstance.getReportfileIds() != null && !serviceInstance.getReportfileIds().isEmpty()){
            //获取最后一个ReportId
            String[] reportFileIdArray = serviceInstance.getReportfileIds().split(",");
            mmap.put("reportId", reportFileIdArray[reportFileIdArray.length - 1]);
        }else {
            mmap.put("reportId", null);
        }
        mmap.put("service", serviceInstance);
        mmap.put("method", method);
        mmap.put("sample", serviceInstance.getSample());
        return prefix + "/viewService";
    }

}
